class JsonCompare:
    def __init__(self, new_data, old_data, is_debug=False):
        """
        This for Json data comparison,
        and output the diffs between the new data and old data

        :param new_data: the new json data
        :param old_data: the json data would be compared to
        :param is_debug: optional param, default to false;
         when set to true, would print the comparison information in console.
        """
        self.new_data = new_data
        self.old_data = old_data
        self.compare_result = []
        self.compare_error = []
        self.defaultroot = ''
        self.compare(new_data, old_data, self.defaultroot)

        # Print the comparison result in console when is_debug set to true
        if is_debug:
            for i in self.compare_result:
                # print(i)
                pass
            for i in self.compare_error:
                # print(i)
                pass

    def compare(self, new_data, old_data, path='/'):
        try:
            if not isinstance(new_data, (list, tuple, dict)):
                # Compare the value if new_data is not list, tuple, and dict.
                # If the value of new_data not equals to the value of old_data,
                # return the difference with a structured json object.
                if not new_data == old_data:
                    msg = {
                        'field': path,
                        'testValue': new_data,
                        'releaseValue': old_data
                    }
                    if new_data is not None or old_data is not None:
                        self.compare_result.append(msg)
            elif isinstance(new_data, (list, tuple)):
                # When new_data is a list or tuple,
                # loop the list or tuple to compare each value of the list.
                if not isinstance(old_data, (list, tuple)):
                    raise IndexError(f'actual value is not a list:{path}')
                for index, value in enumerate(new_data):
                    try:
                        if index < len(old_data):
                            self.compare(
                                value, old_data[index], f'{path}:{index}')
                        else:
                            self.compare(value, {}, f'{path}:{index}')
                    except Exception as e:
                        self.compare_error.append(
                            f'Unknown error: {e.args}')
            else:
                # When new_data is a dict,
                # loop the keys of the dict to compare each value of the dict.
                if not isinstance(new_data, dict):
                    raise IndexError(f'Not a type of dict:{path}')
                for key, value in new_data.items():
                    try:
                        # If key exists in old_data, compare the value.
                        # If key not exists in old_data, check if value is a list or not,
                        # if value is a list, compare the value to a empty list;
                        # if value is not a list, return the result that the value is added.
                        if key in old_data.keys():
                            self.compare(
                                value, old_data[key], f"{path}:{key}")
                        else:
                            if isinstance(value, (list, tuple)):
                                self.compare(
                                    value, [], f"{path}:{key}")
                            else:
                                if value is not None:
                                    msg = {
                                        'field': f"{path}:{key}",
                                        'testValue': value,
                                        'releaseValue': None
                                    }
                                    self.compare_result.append(msg)
                    except Exception as e:
                        self.compare_error.append(
                            f'Unknown error:{e.args}')
        except Exception as e:
            self.compare_error.append(
                f'Unknown error:{e.args}')